namespace Modules
{
	class Downloads
	{
	public:
		Downloads();

		static bool check;

		static struct DecryptedSong_s
		{
			int decryptedtext_len;
			std::string currentSong;
			std::string songName;
			std::string artist;
			std::string album;
			std::string coverart;
			std::string rawSongData;
		} DecryptedSong;

		static struct EncryptedSong_s
		{
			const char* fileID;
			std::string rawSongData;
			std::string rawHostData;
			std::string parsedHost;
			std::string parsedParam;
			std::string decryptionKey;
		} EncryptedSong;

		struct InternetScopedHandle
		{
			InternetScopedHandle(HINTERNET handle)
				: handle(handle) {  }

			HINTERNET handle;

			operator HINTERNET()
			{
				return handle;
			}

			~InternetScopedHandle()
			{
				assert(InternetCloseHandle(handle));
			}
		};

		//https://gist.github.com/guymac/1468279
		class ImageFile : public TagLib::File
		{
		public:
			ImageFile(const wchar_t* file) : TagLib::File(file)
			{

			}

			TagLib::ByteVector data()
			{
				return readBlock(length());
			}

		private:
			virtual TagLib::Tag* tag() const { return 0; }
			virtual TagLib::AudioProperties* audioProperties() const { return 0; }
			virtual bool save() { return false; }
		};

	private:
		static void AddTags(std::wstring filename, std::wstring artist, std::wstring album, std::wstring coverarturl);
		static void DownloadFileProcess();
		static void CmdAddText_stub2(int a1, int a2, const char* fmt, const char* dummy0, int dummy1, int dummy2, int dummy3, int dummy4, int dummy5);
		static void CmdAddText_hk2(int a1, int a2, const char* fmt, const char* dummy0, int dummy1, int dummy2, int dummy3, int dummy4, int dummy5);
		static void GetFileID_stub(int* a1, int a2);
		static void CheckUserInputAndStartDownload();
		static void GetFileID_hk(int* a1, int a2);
		static void AES_set_encrypt_key_stub(unsigned int* key, DWORD* userKey, int bits);
		static void AES_set_encrypt_key_hk(unsigned int* key, DWORD* userKey, int bits);
		static void __fastcall SetLinkAvailableOffline_stub(void* __this, DWORD edx, int a2, int* a3, unsigned int* a4, unsigned int a5, int* a6, unsigned __int8 a7);
		static void __fastcall SetLinkAvailableOffline_hk(void* __this, DWORD edx, int a2, int* a3, unsigned int* a4, unsigned int a5, int* a6, unsigned __int8 a7);
		static void __fastcall Signal_stub(void* _this, DWORD edx, int a2, int a3);
		static void __fastcall Signal_hk(void* _this, DWORD edx, int a2, int a3);
	
		static int decrypt(unsigned char* ciphertext, int ciphertext_len, unsigned char* key, unsigned char* iv, unsigned char* plaintext);

		static std::string GetAccessToken();
		static std::string GetRawSongData();
		static std::string DeleteOGGHeader(std::string rawSongData);
		static std::string HttpRequest(std::string site, std::string param, std::string accessToken, bool isaccessToken);
	};
}